/*
 * OpenFileEntry.h
 *
 *  Created on: Jul 10, 2009
 *      Author: oferbart
 */

#ifndef OPENFILEENTRY_H_
#define OPENFILEENTRY_H_


#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>
#include <sstream>
#include "Utils.h"
#include "MetadataBlock.h"
#include "INode.h"
#include "BlockNode.h"
#include "Utils.h"
#include "Log.h"
#include "HD.h"
#include "Directory.h"
#include "FileSys.h"
#include <utility>
#include <math.h>
#include <errno.h>
#include <pthread.h>
using namespace std;

#define READLOCK 1
#define WRITELOCK 2

#define READ 1
#define WRITE 2
#define READWRITE 3

class OpenFileEntry {
	int _position;
	int _flag;
	int _i_nodeNum;
	int _blockSize;
	int _refCount;
	FileSys* _fs;
	pthread_mutex_t _lock;
	pthread_mutex_t _readLock;
	pthread_mutex_t _writeLock;
	pthread_t  _readLockingThread;
	pthread_t  _writeLockingThread;

	bool _isLockedRead;
	bool _isLockedWrite;

	bool canRead();
	bool canWrite();
	//bool isMutexLocked(pthread_mutex_t* mutex);

	int releaseLockRead(bool supressErrors);
	int releaseLockWrite(bool supressErrors);

public:
	OpenFileEntry(FileSys* fs, int flag, int i_nodeNum, int blockSize);
	OpenFileEntry(OpenFileEntry* oOpenFileEntry);
	virtual ~OpenFileEntry();

	int setPosition(int position);
	int getPosition();
	int relPosition(int offset);

	int incRef();
	int decRef();

	// reads nBytes from the received file into the buffer.
	/// returns number of bytes read.
	int Read (int nBytes, unsigned char* buffer);

	// writes nBytes from buffer into the file.
	/// returns number of bytes written.
	int Write (int nBytes, unsigned char* buffer);

	// locks file, so that only read operations are allowed.
	// There is no limit on the number of processes that are allowed to concurrently read the file.
	// No processes are allowed to write to the file if there is an open read lock on the file.
	// It is not obligatory to lock the file to read it.
	// You should not block if it is locked rather return an error.
	int lockRead();

	// locks file, so that only one process may hold the lock.
	// This process may write to the file, and no other files may write to it or read from it.
	// A child does not inherit this lock. It is not obligatory to lock the file to write to it.
	// You should not block if it is locked rather return an error
	int lockWrite();

	int tryReleaseLockRead();
	int tryReleaseLockWrite();


	// releases the reading lock held by this process.
	// Only the process which locked the file may release the lock.
	int releaseLockRead();

	// releases the writing lock held by this process.
	// Only the process that locked the file may release this lock.
	int releaseLockWrite();

	int getInodeNum();

	int getPermission();
};

#endif /* OPENFILEENTRY_H_ */
